package com.zlk.algorithm.dataStructure.graph.buildSmallTree;

import java.io.*;
import java.util.*;

/**
 * @program: algorithm
 * @ClassName Kruskal  最长用
 * 1 把所有的边，根据权值从小到大排序，从权值小的边开始考虑
 * 2 如果连接当前的边不会形成环，就选择当前的边
 * 3 如果连接当前的边会形成环，就不要当前的边
 * 4 考察完所有边之后，最小生成树的也就得到了
 *
 * 时间复杂度O(m * log m) + O(n) + O(m)
 *
 *
 * // Kruskal算法模版（洛谷）
 * // 静态空间实现
 * // 测试链接 : https://www.luogu.com.cn/problem/P3366  无向图
 * // 请同学们务必参考如下代码中关于输入、输出的处理
 * // 这是输入输出处理效率很高的写法
 * // 提交以下所有代码，把主类名改成Main，可以直接通过
 * @description: 利用并查集
 * @author: slfang
 * @create: 2024-03-21 10:31
 * @Version 1.0
 **/
public class Kruskal {

    //n 节点个数  m边数
    public static int N, M;

    public static int MAXM = 200001;

    public static int[][] edges = new int[MAXM][3];

    public static int[] help = new int[MAXM];
    public static int[] father = new int[MAXM];
    public static int[] size = new int[MAXM];

    public static void build() {
        for (int i = 1; i <= N; i++) {
            father[i] = i;
            size[i] = 1;
        }
    }

    public static boolean isSameSet(int a, int b) {
        return findFather(a) == findFather(b);
    }

    private static int findFather(int cur) {
        int size = 1;
        while (cur != father[cur]) {
            help[size++] = cur;
            cur = father[cur];
        }
        size--;
        while (size >= 1) {
            father[help[size--]] = cur;
        }
        return cur;
    }

    public static void union(int a, int b) {
        if (!isSameSet(a, b)) {
            int fa = findFather(a);
            int fb = findFather(b);
            int sizeA = size[fa];
            int sizeB = size[fb];
            if (sizeA > sizeB) {
                father[fb] = fa;
                size[fa] = sizeA + sizeB;
            } else {
                father[fa] = fb;
                size[fb] = sizeA + sizeB;
            }
        }
    }


    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        StreamTokenizer in = new StreamTokenizer(reader);
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        while (in.nextToken() != -1) {
            N = (int) in.nval;
            in.nextToken();
            M = (int) in.nval;
            // x：  y：    z： 长度
            //下标1开始
            for (int i = 0, x, y, z; i < M; i++) {
                in.nextToken();
                x = (int) in.nval;
                in.nextToken();
                y = (int) in.nval;
                in.nextToken();
                z = (int) in.nval;
                edges[i] = new int[]{x, y, z};
            }

            PriorityQueue<int[]> priorityQueue = new PriorityQueue<>((a, b) -> a[2] - b[2]);
            for (int i = 0; i <M ; i++) {
                priorityQueue.add(edges[i]);
            }
            build();
            int weight = 0;
            int edgeCnt = 0;
            while (!priorityQueue.isEmpty()){
                int[] poll = priorityQueue.poll();
                int x = poll[0];
                int y = poll[1];
                if(!isSameSet(x,y)){
                    union(x,y);
                    weight+=poll[2];
                    edgeCnt++;
                }
            }
            out.println(edgeCnt == N - 1 ? weight : "orz");
        }
        out.flush();
        out.close();
        reader.close();
    }


}




